package com.sunwayworld.basemodule.business.result.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleProductService;
import com.sunwayworld.basemodule.business.folder.bean.LimsFolderBean;
import com.sunwayworld.basemodule.business.folder.bean.LimsOrderBean;
import com.sunwayworld.basemodule.business.folder.bean.LimsPreOrderTaskBean;
import com.sunwayworld.basemodule.business.folder.service.LimsFolderService;
import com.sunwayworld.basemodule.business.folder.service.LimsOrderService;
import com.sunwayworld.basemodule.business.folder.service.LimsPreOrderTaskService;
import com.sunwayworld.basemodule.business.operationbatch.bean.LimsOrderTaskSupplementBean;
import com.sunwayworld.basemodule.business.operationbatch.bean.LimsPreTaskSupplementBean;
import com.sunwayworld.basemodule.business.operationbatch.service.LimsOrderTaskSupplementService;
import com.sunwayworld.basemodule.business.operationbatch.service.LimsPreTaskSupplementService;
import com.sunwayworld.basemodule.business.ordertask.bean.LimsOrderTaskBean;
import com.sunwayworld.basemodule.business.ordertask.service.LimsOrderTaskService;
import com.sunwayworld.basemodule.business.report.bean.LimsReportBean;
import com.sunwayworld.basemodule.business.report.service.LimsReportService;
import com.sunwayworld.basemodule.business.result.bean.LimsResultBean;
import com.sunwayworld.basemodule.business.result.bean.LimsRunBean;
import com.sunwayworld.basemodule.business.result.dao.LimsRunDao;
import com.sunwayworld.basemodule.business.result.service.LimsResultService;
import com.sunwayworld.basemodule.business.result.service.LimsRunService;
import com.sunwayworld.basemodule.common.auditrecord.service.LimsAuditRecordService;
import com.sunwayworld.basemodule.coredata.test.bean.LimsTestSupplementBean;
import com.sunwayworld.basemodule.coredata.test.service.LimsTestSupplementService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleDerivativeBean;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleDerivativeService;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.constant.Constant;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.context.LocalContextHelper;
import com.sunwayworld.framework.executor.ExecutorHelper;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.security.bean.LoginUser;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsRunServiceImpl implements LimsRunService {

    @Autowired
    private LimsRunDao limsRunDao;

    @Lazy
    @Autowired
    private LimsOrderTaskService orderTaskService;

    @Lazy
    @Autowired
    private LimsAuditRecordService auditRecordService;

    @Lazy
    @Autowired
    private LimsResultService resultService;

    @Lazy
    @Autowired
    private LimsOrderService orderService;

    @Lazy
    @Autowired
    private LimsPreOrderTaskService preOrderTaskService;

    @Lazy
    @Autowired
    private LimsFolderService folderService;

    @Lazy
    @Autowired
    private LimsSampleDerivativeService derivativeService;

    @Lazy
    @Autowired
    private LimsSampleService sampleService;

    @Lazy
    @Autowired
    private LimsPreTaskSupplementService preTaskSupplementService;

    @Lazy
    @Autowired
    private LimsOrderTaskSupplementService orderTaskSupplementService;

    @Lazy
    @Autowired
    private LimsTestSupplementService testSupplementService;

    @Lazy
    @Autowired
    private LimsBatchSampleProductService limsBatchSampleProductService;

    @Lazy
    @Autowired
    private LimsReportService reportService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsRunDao getDao() {
        return limsRunDao;
    }

    // 系统参数：REPORT_AD_PRODUCTCODE，阿尔茨海默症检测项目动态匹配模版默认值
    public static final String reportProductCode = "P00032";
    // 检测结论获取指定分析项的值：值名称
    public static final String riskJudgeAnalyte = "风险判定";
    // 风险判定分析项的值
    public static final String higherRisk = "极高风险";
    public static final String highRisk = "高风险";
    public static final String meduimRisk = "中风险";
    public static final String lowRisk = "低风险";

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsRunBean limsRun = jsonWrapper.parseUnique(LimsRunBean.class);
        limsRun.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsRun);
        return limsRun.getId();
    }

    @Transactional
    @Override
    public void submit(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> parse = wrapperBean.parse(LimsRunBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        List<Long> runIds = parse.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR)
                .match("status", "logged").filter(MatchPattern.SB));
        taskBeans.forEach(t -> t.setStatus("approve"));
        orderTaskService.getDao().fastUpdate(taskBeans, "status");
        LocalDateTime now = LocalDateTime.now();
        parse.forEach(t -> {
            t.setStatus("approve");
            t.setEntrySubmitTime(now);
        });
        getDao().fastUpdate(parse, "status", "entrySubmitTime");

        //任务维度插入操作记录
        List<Long> taskIds = taskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_ENTER"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), null);

        List<Long> sampleIds = taskBeans.stream().map(LimsOrderTaskBean::getSampleId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_ENTER"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), null);

    }

    @Transactional
    @Override
    public void passReview(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> parse = wrapperBean.parse(LimsRunBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        List<Long> runIds = parse.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR)
                .match("status", "approve").filter(MatchPattern.SB));
        //任务维度插入操作记录
        List<Long> taskIds = taskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());

        List<Long> folderIdList = taskBeans.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList());
//        copyResult(taskBeans);
        ExecutorHelper.submit(() -> copyResult(taskBeans));

        passReview(taskBeans, true);
        parse.forEach(t -> t.setStatus("done"));
        getDao().fastUpdate(parse, "status");

        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_REVIEW"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), null);

        List<Long> sampleIds = taskBeans.stream().map(LimsOrderTaskBean::getSampleId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_REVIEW"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), null);

        limsBatchSampleProductService.setBatchProductStatus(folderIdList);
    }

    public List<LimsOrderTaskBean> passReview(List<LimsOrderTaskBean> orderTaskBeanList, Boolean flag) {
        if (orderTaskBeanList.isEmpty()) {
            return CollectionUtils.emptyList();
        }
        List<Long> orderTaskIds = new ArrayList<>();
        List<Long> preIds = new ArrayList<>();
        List<Long> orderIds = new ArrayList<>();
        orderTaskBeanList.forEach(orderTaskBean -> {
            orderTaskIds.add(orderTaskBean.getId());
            preIds.add(orderTaskBean.getPreOrderTaskId());
            orderIds.add(orderTaskBean.getOrderId());
        });

        List<LimsSampleDerivativeBean> derivativeBeans = derivativeService.selectListByFilter(SearchFilter.instance().match("orderTaskId", orderTaskIds).filter(MatchPattern.OR));
        if (!derivativeBeans.isEmpty()) {
            List<Long> deriSampleIds = derivativeBeans.stream().map(LimsSampleDerivativeBean::getDerivativeId).distinct().collect(Collectors.toList());
            LimsSampleBean update = new LimsSampleBean();
            update.setHandleType("wait");
            sampleService.getDao().updateByIds(update, deriSampleIds, "handleType");
        }

        //更新order样本关联表状态完成
        LimsOrderTaskBean orderTaskBean = new LimsOrderTaskBean();
        orderTaskBean.setStatus("done");
        orderTaskService.getDao().updateByIds(orderTaskBean, orderTaskIds, "STATUS");

        //更新预工序检测任务状态
        LimsPreOrderTaskBean preOrderTaskBean = new LimsPreOrderTaskBean();
        preOrderTaskBean.setStatus("done");
        preOrderTaskService.getDao().updateByIds(preOrderTaskBean, preIds, "STATUS");

        //校验是否存在分析项异常
        if (flag) {
            getPendingOrderTaskByJudgeType(orderTaskBeanList, orderTaskIds);
        }
        //校验多衍生物情况，该工序是否都完成/终止了 preId相同
        getDerivativeTask(orderTaskBeanList);

        //当所有数据进入异常，则后续不执行
        if (CollectionUtils.isEmpty(orderTaskBeanList)) return CollectionUtils.emptyList();

        return createNextOrderTask(orderTaskBeanList);
    }

    private void getDerivativeTask(List<LimsOrderTaskBean> orderTaskBeanList) {
        List<Long> preIds = orderTaskBeanList.stream().map(LimsOrderTaskBean::getPreOrderTaskId).distinct().collect(Collectors.toList());
        List<LimsOrderTaskBean> orderTaskBeans = orderTaskService.selectListByFilter(SearchFilter.instance().match("preOrderTaskId", preIds).filter(MatchPattern.OR));
        List<String> status = Arrays.asList("done", "stop");
        List<LimsOrderTaskBean> beans = orderTaskBeans.stream().filter(t -> !status.contains(t.getStatus())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(beans)) {
            List<Long> ids = beans.stream().map(LimsOrderTaskBean::getPreOrderTaskId).distinct().collect(Collectors.toList());
            orderTaskBeanList.removeIf(e -> ids.stream().anyMatch(z -> z.equals(e.getPreOrderTaskId())));
        }
    }

    //创建下一道检测工序
    public List<LimsOrderTaskBean> createNextOrderTask(List<LimsOrderTaskBean> tasks) {
        MapperParameter temp = new MapperParameter();

        // 先查衍生物，让有混样的，当前样异常终止，混样其他原样完成的继续流转
        List<Long> ids = tasks.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        List<LimsSampleDerivativeBean> derivativeBeans = derivativeService.selectListByFilter(SearchFilter.instance()
                .match("orderTaskId", ids).filter(MatchPattern.OR)
                .match("useFlag", "1").filter(MatchPattern.EQ));
        List<LimsOrderTaskBean> allTaskBeanList;
        if (!CollectionUtils.isEmpty(derivativeBeans)) {
            // 混样样本的任务是否都完成/终止，是则一起生成下一步工序
            List<Long> mixTaskIds = derivativeBeans.stream().filter(d -> "mix".equalsIgnoreCase(d.getDerivativeType())).map(LimsSampleDerivativeBean::getOrderTaskId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(mixTaskIds)) {// 没有混样
                allTaskBeanList = tasks;
            } else { // 有混样
                allTaskBeanList = tasks.stream().filter(t -> !mixTaskIds.contains(t.getId())).collect(Collectors.toList()); // 没有混样的任务

                List<String> mixSampleNos = derivativeBeans.stream().filter(d -> d.getDerivativeType().equalsIgnoreCase("mix"))
                        .map(LimsSampleDerivativeBean::getDerivativeNo).distinct().collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(mixSampleNos)) {
                    MapperParameter parameter = new MapperParameter();
                    parameter.setFilter(SearchFilter.instance().match("derivativeNo", mixSampleNos).filter(MatchPattern.OR));
                    List<LimsOrderTaskBean> orderTaskBeans = orderTaskService.selectDerivativeTask(parameter);
                    //混样样本的任务是否都完成，都完成一起处理，
                    for (String derivativeNo : mixSampleNos) {
                        List<LimsOrderTaskBean> mixTaskBeans = orderTaskBeans.stream().filter(t -> derivativeNo.equalsIgnoreCase(t.getExt$Item("derivativeNo"))).collect(Collectors.toList());
                        // 混样的任务全部完成/终止，则完成的进行下一步
                        if (mixTaskBeans.stream().allMatch(t -> "done".equalsIgnoreCase(t.getStatus()) || "stop".equalsIgnoreCase(t.getStatus()))) {
                            allTaskBeanList.addAll(mixTaskBeans.stream().filter(t -> "done".equalsIgnoreCase(t.getStatus())).collect(Collectors.toList()));
                        }
                    }
                }
            }
        } else {
            allTaskBeanList = tasks;
        }
        // ---- 混样任务都完成了一起流转
        if (CollectionUtils.isEmpty(allTaskBeanList)) return CollectionUtils.emptyList();

        // 再次筛出完成的任务继续流转
        List<Long> preIds = allTaskBeanList.stream().map(LimsOrderTaskBean::getPreOrderTaskId).distinct().collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeanList = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("preOrderTaskId", preIds).filter(MatchPattern.OR)
                .match("status", "done").filter(MatchPattern.EQ));
        if (CollectionUtils.isEmpty(taskBeanList)) return CollectionUtils.emptyList();

        // 衍生物关系表
        ids = taskBeanList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        derivativeBeans = derivativeService.selectListByFilter(SearchFilter.instance()
                .match("orderTaskId", ids).filter(MatchPattern.OR)
                .match("useFlag", "1").filter(MatchPattern.EQ));

        List<Long> folderIds = taskBeanList.stream().map(LimsOrderTaskBean::getFolderId).collect(Collectors.toList());
        //获取下一道预检测工序
        temp.setFilter(SearchFilter.instance().match("folderId", folderIds).filter(MatchPattern.OR));
        temp.setFilter(SearchFilter.instance().match("STATUS", "draft").filter(MatchPattern.SEQ));
        List<LimsPreOrderTaskBean> relationPreOrderTaskList = preOrderTaskService.selectList(temp);
        if (CollectionUtils.isEmpty(relationPreOrderTaskList)) {
            completeTaskToDone(taskBeanList);
            return CollectionUtils.emptyList();
        }
        Map<Long, List<LimsPreOrderTaskBean>> relationPreOrderTaskMaps = relationPreOrderTaskList.stream().distinct().collect(Collectors.groupingBy(LimsPreOrderTaskBean::getFolderId));


        //获取order 的样本信息
        List<Long> orderIds = taskBeanList.parallelStream().map(LimsOrderTaskBean::getOrderId).collect(Collectors.toList());
        List<LimsOrderBean> orderBeans = orderService.selectListByIds(orderIds);

        // 衍生物order
        List<LimsOrderBean> derivativeOrderList = new ArrayList<>();
        // 衍生物preOrderTask
        List<LimsPreOrderTaskBean> nextPreorderTaskList = new ArrayList<>();
        // 衍生物OrderTask
        List<LimsOrderTaskBean> nextOrderTaskList = new ArrayList<>();
        // 已完成工序orderTask
        List<LimsOrderTaskBean> completeOrderTakList = new ArrayList<>();

        for (LimsOrderTaskBean oldOrderTaskBean : taskBeanList) {
            // 判断是否存在衍生物, 存在则衍生物进行工序
            Optional<LimsSampleDerivativeBean> optionalMixDerivative = derivativeBeans.stream().filter(d -> d.getOrderTaskId().equals(oldOrderTaskBean.getId())).findFirst();
            // 获取剩下的预检测工序
            List<LimsPreOrderTaskBean> preOrderTasks = relationPreOrderTaskMaps.get(oldOrderTaskBean.getFolderId());
            if (CollectionUtils.isEmpty(preOrderTasks)) {
                completeOrderTakList.add(oldOrderTaskBean);//实验模板已完成，最后一道工序
            } else {
                List<LimsPreOrderTaskBean> preOrderTaskBeans = relationPreOrderTaskMaps.get(oldOrderTaskBean.getFolderId()).stream().sorted(Comparator.comparing(LimsPreOrderTaskBean::getSort)).collect(Collectors.toList());
                if (optionalMixDerivative.isPresent()) {
                    // 有衍生物，衍生物继续任务
                    List<LimsSampleDerivativeBean> collect = derivativeBeans.stream().filter(d -> d.getOrderTaskId().equals(oldOrderTaskBean.getId())).collect(Collectors.toList());
                    for (LimsSampleDerivativeBean derivativeBean : collect) {
                        LimsOrderBean derivativeOrder = new LimsOrderBean();
                        derivativeOrder.setId(ApplicationContextHelper.getNextIdentity());
                        derivativeOrder.setStatus("draft");
                        derivativeOrder.setSampleId(derivativeBean.getDerivativeId());
                        derivativeOrder.setSampleCode(derivativeBean.getDerivativeNo());
                        derivativeOrder.setSampleTypeName(derivativeBean.getExt$Item("sampleType"));
                        derivativeOrder.setSampleTypeCode(derivativeBean.getExt$Item("sampleTypeCode"));
                        derivativeOrder.setFolderId(oldOrderTaskBean.getFolderId());
                        if ("mix".equalsIgnoreCase(derivativeBean.getDerivativeType())) {
                            derivativeOrder.setOrderType("M");
                        } else {
                            derivativeOrder.setOrderType("D");
                        }
                        derivativeOrderList.add(derivativeOrder);
                        for (LimsPreOrderTaskBean nextPreOrderTaskBean : preOrderTaskBeans) {
                            if (!StringUtils.isBlank(nextPreOrderTaskBean.getLastEtTestIds()) && checkExists(nextPreOrderTaskBean.getLastEtTestIds(), String.valueOf(oldOrderTaskBean.getEtTestId()))) {
                                insertOrderTaskList(derivativeOrder,
                                        oldOrderTaskBean,
                                        nextPreOrderTaskBean,
                                        nextOrderTaskList,
                                        nextPreorderTaskList,
                                        derivativeBean);
                                continue;
                            }
                            if (StringUtils.isBlank(nextPreOrderTaskBean.getLastEtTestIds())) {
                                insertOrderTaskList(derivativeOrder,
                                        oldOrderTaskBean,
                                        nextPreOrderTaskBean,
                                        nextOrderTaskList,
                                        nextPreorderTaskList,
                                        derivativeBean);
                            }
                        }
                    }
                    continue;
                }
                for (LimsPreOrderTaskBean nextPreOrderTaskBean : preOrderTaskBeans) {
                    //关联工序需要符合条件下发
                    if (!StringUtils.isBlank(nextPreOrderTaskBean.getLastEtTestIds()) && checkExists(nextPreOrderTaskBean.getLastEtTestIds(), String.valueOf(oldOrderTaskBean.getEtTestId()))) {
                        insertOrderTaskList(null,
                                oldOrderTaskBean,
                                nextPreOrderTaskBean,
                                nextOrderTaskList,
                                nextPreorderTaskList,
                                null);
                        continue;
                    }
                    //当没有关联工序，则后续任务都需要被产生
                    if (StringUtils.isBlank(nextPreOrderTaskBean.getLastEtTestIds())) {
                        insertOrderTaskList(null,
                                oldOrderTaskBean,
                                nextPreOrderTaskBean,
                                nextOrderTaskList,
                                nextPreorderTaskList,
                                null);
                    }
                }
            }
        }


        //插入衍生物任务
        if (!CollectionUtils.isEmpty(derivativeOrderList)) {

            orderService.getDao().fastInsert(derivativeOrderList);

            List<Long> completeOrderIds = orderBeans.stream().filter(o -> derivativeOrderList.stream()
                            .anyMatch(d -> d.getFolderId().equals(o.getFolderId())))
                    .map(LimsOrderBean::getId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(completeOrderIds)) {
                LimsOrderBean completeOrderBean = new LimsOrderBean();
                completeOrderBean.setStatus("done");
                orderService.getDao().updateByIds(completeOrderBean, completeOrderIds, "STATUS");
            }
        }
        //插入新的工序任务和更改
        if (!CollectionUtils.isEmpty(nextOrderTaskList)) {
            //插入新工序
            orderTaskService.getDao().fastInsert(nextOrderTaskList);
            markParallel(nextOrderTaskList);// 混样并行任务标记
            //更新
            preOrderTaskService.getDao().fastUpdate(nextPreorderTaskList, "STATUS", "ORDERTASKID");
            // 判断后续工序是否分配相同SOP(暂不考虑平行工序)

            // 产生下一道工序的补充信息
//            createNextTaskSupplement(nextOrderTaskList);

            LoginUser loginUser = LocalContextHelper.getLoginPrincipal();
            // 产生下一道工序的补充信息
            ExecutorHelper.submit(() -> {
                LocalContextHelper.setUserLogin(loginUser);
                createNextTaskSupplement(nextOrderTaskList);
            });
        }
        if (!CollectionUtils.isEmpty(completeOrderTakList)) {
            completeTaskToDone(completeOrderTakList);
        }
        return nextOrderTaskList;
    }

    private void createNextTaskSupplement(List<LimsOrderTaskBean> nextOrderTaskList) {
        if (nextOrderTaskList.isEmpty()) return;
        // 重新查询获取下发批次信息
        MapperParameter temp = new MapperParameter();
        List<Long> idList = nextOrderTaskList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        temp.put("orderTaskIds", StringUtils.join(idList, ","));
        nextOrderTaskList = orderTaskService.selectPreFolderByOrderTask(temp);

        List<Long> testIds = nextOrderTaskList.stream().map(LimsOrderTaskBean::getTestId).distinct().collect(Collectors.toList());
        List<LimsTestSupplementBean> testSupplementBeans = testSupplementService.getDao().selectListByOneColumnValues(testIds, "testId");
        if (testSupplementBeans.isEmpty()) return;
        Map<Long, List<LimsTestSupplementBean>> testSupplementMaps = testSupplementBeans.stream().collect(Collectors.groupingBy(LimsTestSupplementBean::getTestId));

        List<Long> lastOrderTaskIds = nextOrderTaskList.stream().map(LimsOrderTaskBean::getLastOrderTaskId).collect(Collectors.toList());
        List<Long> preFolderIds = nextOrderTaskList.stream().map(e -> NumberUtils.parseLong(e.getExt$Item("preFolderId"))).collect(Collectors.toList());
        // 获取批次补充信息
        List<LimsPreTaskSupplementBean> preTaskSupplementBeans = preTaskSupplementService.getDao().selectListByOneColumnValues(preFolderIds, "preFolderId")
                .stream().filter(e -> !StringUtils.isBlank(e.getFieldValue())).collect(Collectors.toList());
        // 获取工序补充信息
        List<LimsOrderTaskSupplementBean> orderTaskSupplementBeans = orderTaskSupplementService.getDao().selectListByOneColumnValues(lastOrderTaskIds, "orderTaskId")
                .stream().filter(e -> !StringUtils.isBlank(e.getFieldValue())).collect(Collectors.toList());
        // 获取分析项信息
        List<LimsResultBean> resultBeans = resultService.getDao().selectListByOneColumnValues(lastOrderTaskIds, "orderTaskId")
                .stream().filter(e -> !StringUtils.isBlank(e.getFinalResult())).collect(Collectors.toList());

        List<LimsOrderTaskSupplementBean> insertOrderTaskSupplements = new ArrayList<>();
        for (LimsOrderTaskBean taskBean : nextOrderTaskList) {
            List<LimsTestSupplementBean> testSupplementList = testSupplementMaps.get(taskBean.getTestId());
            if (CollectionUtils.isEmpty(testSupplementList)) continue;
            Map<String, List<LimsTestSupplementBean>> supplementMaps = testSupplementList.stream()
                    .sorted(Comparator.comparingLong(LimsTestSupplementBean::getOrderNo))
                    .collect(Collectors.groupingBy(LimsTestSupplementBean::getInformation));

            for (String s : supplementMaps.keySet()) {
                LimsTestSupplementBean bean = supplementMaps.get(s).get(0);
                LimsOrderTaskSupplementBean orderTaskSupplementBean = new LimsOrderTaskSupplementBean();
                orderTaskSupplementBean.setId(ApplicationContextHelper.getNextIdentity());
                orderTaskSupplementBean.setOperationBatch(taskBean.getExt$Item("operationBatch"));
                orderTaskSupplementBean.setPreFolderId(NumberUtils.parseLong(taskBean.getExt$Item("preFolderId")));
                orderTaskSupplementBean.setOrderTaskId(taskBean.getId());
                orderTaskSupplementBean.setFieldName(bean.getInformation());
                orderTaskSupplementBean.setFieldValue(bean.getDefaultValue());
                orderTaskSupplementBean.setRequiredFlag(bean.getRequiredFlag());
                orderTaskSupplementBean.setOrderNo(bean.getOrderNo());
                orderTaskSupplementBean.setUnit(bean.getUnit());

                if (!preTaskSupplementBeans.isEmpty()) {
                    preTaskSupplementBeans.stream().filter(e -> e.getPreFolderId().equals(orderTaskSupplementBean.getPreFolderId())
                                    && StringUtils.equals(e.getFieldName(), orderTaskSupplementBean.getFieldName()))
                            .forEach(e -> orderTaskSupplementBean.setFieldValue(e.getFieldValue()));
                }

                if (!orderTaskSupplementBeans.isEmpty()) {
                    orderTaskSupplementBeans.stream().filter(e -> e.getOrderTaskId().equals(taskBean.getLastOrderTaskId())
                                    && StringUtils.equals(e.getFieldName(), orderTaskSupplementBean.getFieldName()))
                            .forEach(e -> orderTaskSupplementBean.setFieldValue(e.getFieldValue()));
                }
                // 判断是否需要从分析项中带入
                if (StringUtils.equals(bean.getGainAnalyteFlag(), Constant.YES) && !resultBeans.isEmpty()) {
                    resultBeans.stream().filter(e -> e.getOrderTaskId().equals(taskBean.getLastOrderTaskId())
                                    && StringUtils.equals(e.getAnalyte(), orderTaskSupplementBean.getFieldName()))
                            .forEach(e -> orderTaskSupplementBean.setFieldValue(e.getFinalResult()));
                }
                insertOrderTaskSupplements.add(orderTaskSupplementBean);
            }
        }
        orderTaskSupplementService.getDao().fastInsert(insertOrderTaskSupplements);
    }

    private void markParallel(List<LimsOrderTaskBean> orderTaskBeans) {
        if (CollectionUtils.isEmpty(orderTaskBeans)) {
            return;
        }
        List<LimsOrderTaskBean> mark = new ArrayList<>();
        // 混过样的，进行混样标记，同样本同工序的只显示一条
        Map<String, List<LimsOrderTaskBean>> collect = orderTaskBeans.stream().filter(o -> o.getMixCode() != null)
                .collect(Collectors.groupingBy(LimsOrderTaskBean::getSampleCode));
        collect.forEach((sampleCode, list) -> {
            if (list.size() > 1) {
                Map<Long, List<LimsOrderTaskBean>> testMap = list.stream().collect(Collectors.groupingBy(LimsOrderTaskBean::getTestId));
                testMap.forEach((testId, tasks) -> { //混样，同一工序，标记
                    if (tasks.size() > 1) {
                        Long parallelId = tasks.get(0).getParallelId();
                        for (int i = 0; i < tasks.size(); i++) {
                            if (i > 0) {
                                tasks.get(i).setParallelId(parallelId);
                                tasks.get(i).setFlag(Constant.NO);
                            }
                        }
                        mark.addAll(tasks);
                    }
                });
            }
        });
        if (!mark.isEmpty()) {
            orderTaskService.getDao().fastUpdate(mark, "flag", "parallelId");
        }
    }

    //校验
    private boolean checkExists(String x, String y) {
        String a = "," + x + ",";
        String b = "," + y + ",";
        return a.contains(b);
    }

    //工序任务单
    private void insertOrderTaskList(LimsOrderBean orderBean,  // 衍生物新order
                                     LimsOrderTaskBean oldOrderTaskBean,
                                     LimsPreOrderTaskBean nextPreOrderTaskBean,
                                     List<LimsOrderTaskBean> nextOrderTaskList,
                                     List<LimsPreOrderTaskBean> nextPreorderTaskList,
                                     LimsSampleDerivativeBean derivativeBean) {
        LimsOrderTaskBean orderTaskBean = new LimsOrderTaskBean();
        BeanUtils.copyProperties(nextPreOrderTaskBean, orderTaskBean, "id", "createdById", "createdByName", "createdTime", "createdByOrgId", "createdByOrgName");
        orderTaskBean.setBatchId(oldOrderTaskBean.getBatchId());
        orderTaskBean.setBatchCode(oldOrderTaskBean.getBatchCode());
        orderTaskBean.setFolderId(oldOrderTaskBean.getFolderId());
        if (derivativeBean != null) {
            //当存在衍生物，则下道工序需要关联衍生物id
            orderTaskBean.setOrderId(orderBean.getId());
            orderTaskBean.setSampleId(orderBean.getSampleId());
            orderTaskBean.setSampleCode(orderBean.getSampleCode());
            if ("mix".equalsIgnoreCase(derivativeBean.getDerivativeType())
                    || (!StringUtils.isEmpty(derivativeBean.getOriNo()) && derivativeBean.getOriNo().contains(","))) {
                // 混样的，判断下游工序一样的，进行标记
                orderTaskBean.setMixCode(orderBean.getSampleCode());
            }
        } else {
            orderTaskBean.setOrderId(oldOrderTaskBean.getOrderId());
            orderTaskBean.setSampleId(oldOrderTaskBean.getSampleId());
            orderTaskBean.setSampleCode(oldOrderTaskBean.getSampleCode());
            orderTaskBean.setMixCode(oldOrderTaskBean.getMixCode()); //没产生衍生物，继承上一步的混样编号
        }

        orderTaskBean.setId(ApplicationContextHelper.getNextIdentity());
        orderTaskBean.setPreOrderTaskId(nextPreOrderTaskBean.getId());
        orderTaskBean.setStatus("draft");
        orderTaskBean.setLastOrderTaskId(oldOrderTaskBean.getId()); //上一步ORDERTASKID
        orderTaskBean.setLastParallelId(oldOrderTaskBean.getParallelId()); // 上一步并任务ID

        orderTaskBean.setParallelId(ApplicationContextHelper.getNextIdentity());
        nextOrderTaskList.add(orderTaskBean);

        nextPreOrderTaskBean.setStatus("logged");
        nextPreOrderTaskBean.setOrderTaskId(orderTaskBean.getId());
        nextPreorderTaskList.add(nextPreOrderTaskBean);
    }

    public void getPendingOrderTaskByJudgeType(List<LimsOrderTaskBean> orderTaskBeanList, List<Long> orderTaskIds) {
        MapperParameter temp = new MapperParameter();
        temp.put("ordtaskIds", StringUtils.join(orderTaskIds, ","));
        List<LimsOrderTaskBean> orderTaskPendingBeanList = resultService.selectResultByJudgeType(temp);
        if (!orderTaskPendingBeanList.isEmpty()) {
            String reason = "系统自动判别";
            // 待处理卡流程
            List<Long> pendingOrderTaskIds = orderTaskPendingBeanList.stream().map(LimsOrderTaskBean::getId).distinct().collect(Collectors.toList());
            orderTaskBeanList.removeIf(e -> pendingOrderTaskIds.stream().anyMatch(z -> z.equals(e.getId())));
            LimsOrderTaskBean orderTaskBean = new LimsOrderTaskBean();
            orderTaskBean.setReason(reason);
            orderTaskBean.setStatus("abnormal");
            orderTaskService.getDao().updateByIds(orderTaskBean, pendingOrderTaskIds, "STATUS", "REASON");

            List<Long> pendingPreIds = orderTaskPendingBeanList.stream().map(LimsOrderTaskBean::getPreOrderTaskId).distinct().collect(Collectors.toList());
            LimsPreOrderTaskBean preOrderTaskBean = new LimsPreOrderTaskBean();
            preOrderTaskBean.setStatus("abnormal");
            preOrderTaskService.getDao().updateByIds(preOrderTaskBean, pendingPreIds, "STATUS");
        }
    }

    @Transactional
    public void completeTaskToDone(List<LimsOrderTaskBean> completeOrderTakList) {
        List<Long> folderIds = new ArrayList<>();
        List<Long> orderIds = new ArrayList<>();
        completeOrderTakList.forEach(ordertask -> {
            folderIds.add(ordertask.getFolderId());
            orderIds.add(ordertask.getOrderId());
        });
        // 更新folder状态
        LimsFolderBean updateFolderBean = new LimsFolderBean();
        updateFolderBean.setStatus("done");
        folderService.getDao().updateByIds(updateFolderBean, folderIds, "status");
        // 更新order状态
        LimsOrderBean updateStatusOrderBean = new LimsOrderBean();
        updateStatusOrderBean.setStatus("done");
        orderService.getDao().updateByIds(updateStatusOrderBean, orderIds, "STATUS");

        // 生成报告
        MapperParameter parameter = new MapperParameter();
        parameter.setFilter(SearchFilter.instance().match("id", folderIds).filter(MatchPattern.OR));
        parameter.setFilter(SearchFilter.instance().match("batchCode", "QC001").filter(MatchPattern.DIFFER));
        // 会出现重复，项目在多个报告模板下
        // ad-阿尔茨海默症会有四个不同的模版，都对应该检测项目，需特殊处理，按当前报告下的分析项名称为：风险判定，值分贝对应四项报告
        // 分析项值：低风险，中风险，高风险，极高风险
        List<LimsFolderBean> folderBeans = folderService.selectForReport(parameter);
        List<Long> doneFolderIds = folderBeans.stream().map(LimsFolderBean::getId).distinct().collect(Collectors.toList());
        // 获取系统参数，阿尔茨海默症，特定模版匹配的检测项目编码：REPORT_AD_PRODUCTCODE
        // 获取系统参数，默认值为：P00032，支持多个值用英文逗号分割
        String reportProductCodes = ApplicationContextHelper.getConstantValue("REPORT_AD_PRODUCTCODE", reportProductCode);
        // 获取完成folder涉及的检测项目
        List<String> productCodes = folderBeans.stream().map(LimsFolderBean::getProductCode).distinct().collect(Collectors.toList());
        // 是否需动态匹配报告模版，有一个即true
        boolean dynamicReport = productCodes.stream().anyMatch(u->productCodes.contains(u));
        // 名称为风险判定的分析项
        List<LimsResultBean> results = null;
        if (true) {
            results = resultService.selectListByFilter(SearchFilter.instance()
                .match("FOLDERID", doneFolderIds).filter(MatchPattern.OR)
                .match("ANALYTE", riskJudgeAnalyte).filter(MatchPattern.SEQ));
        }
        List<LimsReportBean> reportBeans = new ArrayList<>();
        List<LimsOrderTaskBean> oTasks = orderTaskService.getDao().selectListByOneColumnValues(doneFolderIds, "folderId", Arrays.asList("folderId", "id"));
        for (Long id : doneFolderIds) {
            List<LimsFolderBean> collect = folderBeans.stream().filter(f -> id.equals(f.getId())).collect(Collectors.toList());
            LimsFolderBean folderBean = collect.get(0);
            LimsReportBean limsReportBean = new LimsReportBean();
            limsReportBean.setId(ApplicationContextHelper.getNextIdentity());
            limsReportBean.setReportNo(ApplicationContextHelper.getNextSequence(reportService.getDao().getTable()));
            limsReportBean.setBatchId(folderBean.getBatchId());
            limsReportBean.setBatchCode(folderBean.getBatchCode());
            limsReportBean.setProductId(folderBean.getProductId());
            limsReportBean.setProductCode(folderBean.getProductCode());
            limsReportBean.setProductName(folderBean.getProductName());
            limsReportBean.setSampleIds(folderBean.getExt$Item("sampleId"));
            limsReportBean.setSampleCodes(folderBean.getExt$Item("sampleCode"));
            limsReportBean.setHissampleCodes(folderBean.getExt$Item("hissampleCode"));
            limsReportBean.setFolderIds(String.valueOf(id));
            limsReportBean.setType(folderBean.getExt$Item("type"));
            // 生成报告时添加最后一步工序的id
            limsReportBean.setLastOrderTaskId(oTasks.stream().filter(ot -> ot.getFolderId().equals(id)).map(LimsOrderTaskBean::getId).max(Long::compareTo).orElse(null));
            // 报告模板（原始报告模版id，非关联中间表的项目报告模版id）
            List<LimsFolderBean> re = collect.stream().filter(f -> f.getExt$Item("templateId") != null).collect(Collectors.toList());
            // 最终匹配到的模版
            LimsFolderBean finalFolder = null;
            // 唯一报告模板
            if (re.size() == 1) {
                finalFolder = re.get(0);
            } else if (re.size() == 0) {
                finalFolder = null;
            } else {
                // 如果是ad动态匹配模版，且风险判定有值，则唯一匹配
                if (reportProductCodes.contains(folderBean.getProductCode())) {
                    // ad项目，但无"风险判定"分析项，默认取低风险的报告模版，若无，再随机去一个
                    if (results == null || CollectionUtils.isEmpty(results)) {
                        // ad动态匹配但是没有"风险判定"分析项，默认取模版中的低风险模版
                        Optional<LimsFolderBean> lowTmpOp = re.stream()
                            .filter(u->!StringUtils.isEmpty(u.getExt$Item("TEMPLATENAME"))
                            && u.getExt$Item("TEMPLATENAME").contains(lowRisk)).findAny();
                        if (lowTmpOp.isPresent()) {
                            // 匹配到了低风险的模版
                            finalFolder = lowTmpOp.get();
                        } else {
                            // 随机取一个
                            Optional<LimsFolderBean> any = re.stream().findAny();
                            if (any.isPresent()) {
                                finalFolder = any.get();
                            }
                        }
                    } else {
                        // 获取当前folder的风险判定分析项
                        List<LimsResultBean> riskJudgeResults = results.stream()
                            .filter(u->ObjectUtils.equals(u.getFolderId(), id)).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(riskJudgeResults)) {
                            // 极高风险
                            Optional<LimsResultBean> higherOp = riskJudgeResults.stream()
                                .filter(u->StringUtils.equals(u.getFinalResult(), higherRisk)).findAny();
                            if (higherOp.isPresent()) {
                                // 项目报告中的模版名称，包含极高风险
                                Optional<LimsFolderBean> hignerTmpOp = re.stream()
                                    .filter(u->!StringUtils.isEmpty(u.getExt$Item("TEMPLATENAME"))
                                    && u.getExt$Item("TEMPLATENAME").contains(higherRisk)).findAny();
                                if (hignerTmpOp.isPresent()) {
                                    // 匹配到了极高风险的模版
                                    finalFolder = hignerTmpOp.get();
                                }
                            }
                            if (finalFolder == null) {
                                // 高风险
                                Optional<LimsResultBean> highOp = riskJudgeResults.stream()
                                    .filter(u->StringUtils.equals(u.getFinalResult(), highRisk)).findAny();
                                if (highOp.isPresent()) {
                                    // 项目报告中的模版名称，包含高风险
                                    Optional<LimsFolderBean> highTmpOp = re.stream()
                                        .filter(u->!StringUtils.isEmpty(u.getExt$Item("TEMPLATENAME"))
                                        && u.getExt$Item("TEMPLATENAME").contains(highRisk)).findAny();
                                    if (highTmpOp.isPresent()) {
                                        // 匹配到了高风险的模版
                                        finalFolder = highTmpOp.get();
                                    }
                                }
                            }
                            if (finalFolder == null) {
                                // 中风险
                                Optional<LimsResultBean> mediumOp = riskJudgeResults.stream()
                                    .filter(u->StringUtils.equals(u.getFinalResult(), meduimRisk)).findAny();
                                if (mediumOp.isPresent()) {
                                    // 项目报告中的模版名称，包含中风险
                                    Optional<LimsFolderBean> meduimTmpOp = re.stream()
                                        .filter(u->!StringUtils.isEmpty(u.getExt$Item("TEMPLATENAME"))
                                        && u.getExt$Item("TEMPLATENAME").contains(meduimRisk)).findAny();
                                    if (meduimTmpOp.isPresent()) {
                                        // 匹配到了中风险的模版
                                        finalFolder = meduimTmpOp.get();
                                    }
                                }
                            }
                            if (finalFolder == null) {
                                // 低风险
                                Optional<LimsResultBean> lowOp = riskJudgeResults.stream()
                                    .filter(u->StringUtils.equals(u.getFinalResult(), lowRisk)).findAny();
                                if (lowOp.isPresent()) {
                                    // 项目报告中的模版名称，包含低风险
                                    Optional<LimsFolderBean> lowTmpOp = re.stream()
                                        .filter(u->!StringUtils.isEmpty(u.getExt$Item("TEMPLATENAME"))
                                        && u.getExt$Item("TEMPLATENAME").contains(lowRisk)).findAny();
                                    if (lowTmpOp.isPresent()) {
                                        // 匹配到了低风险的模版
                                        finalFolder = lowTmpOp.get();
                                    }
                                }
                            }
                            if (finalFolder == null) {
                                // 匹配了一遍还未找到，随机一个
                                Optional<LimsFolderBean> any = re.stream().findAny();
                                if (any.isPresent()) {
                                    finalFolder = any.get();
                                }
                            }
                        } else {
                            // ad动态匹配但是没有"风险判定"分析项，默认取模版中的低风险模版
                            Optional<LimsFolderBean> lowTmpOp = re.stream()
                                .filter(u->!StringUtils.isEmpty(u.getExt$Item("TEMPLATENAME"))
                                && u.getExt$Item("TEMPLATENAME").contains(lowRisk)).findAny();
                            if (lowTmpOp.isPresent()) {
                                // 匹配到了低风险的模版
                                finalFolder = lowTmpOp.get();
                            } else {
                                // 随机取一个
                                Optional<LimsFolderBean> any = re.stream().findAny();
                                if (any.isPresent()) {
                                    finalFolder = any.get();
                                }
                            }
                        }
                    }
                } else {
                    // 同检测项目多模版，则默认随机取一个，和客户不再关联
                    Optional<LimsFolderBean> any = re.stream().findAny();
                    if (any.isPresent()) {
                        finalFolder = any.get();
                    }
                }
            }
            // 设置模版信息
            if (finalFolder != null && finalFolder.getExt$Item("templateId") != null) {
                limsReportBean.setReportTemplateId(Long.parseLong(finalFolder.getExt$Item("templateId")));
                limsReportBean.setReportTemplateCode(finalFolder.getExt$Item("templateCode"));
                limsReportBean.setReportTemplateName(finalFolder.getExt$Item("templateName"));
            }
            reportBeans.add(limsReportBean);
        }

        reportService.getDao().insert(reportBeans);

        // 如果匹配了报告模版，则自动生成pdf和docx格式的两份报告，生成的报告里边的数据未填充，可能和报告生成机制有关，无法读未提交的数据
        // List<LimsReportBean> generateReports = reportBeans.stream()
        //     .filter(u->!ObjectUtils.isEmpty(u.getReportTemplateId())).collect(Collectors.toList());
        // if (!CollectionUtils.isEmpty(generateReports)) {
        //     List<Long> reportIds = reportBeans.stream().map(LimsReportBean::getId).collect(Collectors.toList());
        //     reportService.autoCreateReports(reportIds);
        // }

        // 样本所有任务都完成，则样本更新完成状态
        List<String> sampleCodes = folderBeans.stream().map(LimsFolderBean::getOriNo).distinct().collect(Collectors.toList());
        List<LimsFolderBean> folderBeanList = folderService.selectListByFilter(SearchFilter.instance()
                .match("oriNo", sampleCodes).filter(MatchPattern.OR)
                .match("status", "done").filter(MatchPattern.DIFFER));
        List<String> doneSample = sampleCodes.stream().filter(s -> folderBeanList.stream()
                .noneMatch(f -> f.getOriNo().equalsIgnoreCase(s))).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(doneSample)) {
            List<LimsSampleBean> doneSampleList = sampleService.getDao().selectListByOneColumnValues(doneSample, "sampleCode");
            doneSampleList.forEach(s -> s.setStatus("done"));
            sampleService.getDao().fastUpdate(doneSampleList, "status");
        }

    }

    // 提交时给样本同工序任务复制结果
    private void copyResult(List<LimsOrderTaskBean> limsOrderTaskBeans) {
        // 待复制的任务
        List<LimsOrderTaskBean> collect = limsOrderTaskBeans.stream().filter(t -> Constant.NO.equalsIgnoreCase(t.getFlag())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)) {
            return;
        }
        // 复制源
        List<LimsOrderTaskBean> taskBeans = limsOrderTaskBeans.stream().filter(o -> Constant.YES.equalsIgnoreCase(o.getFlag())
                && collect.stream().anyMatch(t -> t.getParallelId().equals(o.getParallelId()))).collect(Collectors.toList());

        List<Long> taskIds = collect.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        taskIds.addAll(taskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList()));
        List<LimsResultBean> results = resultService.selectListByFilter(SearchFilter.instance().match("orderTaskId", taskIds).filter(MatchPattern.OR));

        List<LimsResultBean> updates = new ArrayList<>();
        for (LimsOrderTaskBean taskBean : collect) {
            Optional<LimsOrderTaskBean> first = taskBeans.stream()
                    .filter(o -> Constant.YES.equalsIgnoreCase(o.getFlag()) && taskBean.getParallelId().equals(o.getParallelId())).findFirst();
            if (first.isPresent()) {
                LimsOrderTaskBean bean = first.get();
                List<LimsResultBean> resultBeans = results.stream().filter(r -> r.getOrderTaskId().equals(taskBean.getId())).collect(Collectors.toList());// 待复制的结果
                List<LimsResultBean> origResults = results.stream().filter(r -> r.getOrderTaskId().equals(bean.getId())).collect(Collectors.toList());// 已录入的结果
                // 分析项标记了继承的，就不复制
                resultBeans.stream().filter(r -> !StringUtils.equals(r.getInherit(), Constant.YES)).forEach(r -> {
                    LimsResultBean resultBean = origResults.stream().filter(o -> o.getAnalyteId().equals(r.getAnalyteId())).findFirst().orElseGet(null);
                    if (resultBean != null) {
                        r.setOriginalResult(resultBean.getOriginalResult());
                        r.setFinalResult(resultBean.getFinalResult());
                        r.setJudge(resultBean.getJudge());
                        updates.add(r);
                    }
                });
            }
        }
        resultService.getDao().fastUpdate(updates, "originalResult", "finalResult", "judge");
    }

    @Override
    public void rejectReview(RestJsonWrapperBean wrapperBean) {
        List<LimsRunBean> parse = wrapperBean.parse(LimsRunBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        String reason = wrapperBean.getParamValue("reason");
        List<Long> runIds = parse.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));
        taskBeans.forEach(t -> t.setStatus("logged"));
        orderTaskService.getDao().fastUpdate(taskBeans, "status");
        parse.forEach(t -> {
            t.setStatus("logged");
            t.setReviewRejectReason(reason);
        });
        getDao().fastUpdate(parse, "status", "reviewRejectReason");

        //任务维度插入操作记录
        List<Long> taskIds = taskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_REVIEW"), I18nHelper.getMessage("GIKAM.BPMN.COMMENT.REJECT"), null);

        List<Long> sampleIds = taskBeans.stream().map(LimsOrderTaskBean::getSampleId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_REVIEW"), I18nHelper.getMessage("GIKAM.BPMN.COMMENT.REJECT"), null);

    }

    @Transactional
    @Override
    public void abnormal(RestJsonWrapperBean wrapperBean) {
        List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        List<LimsOrderTaskBean> orderTaskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("parallelId", parallelIds).filter(MatchPattern.OR));
        List<Long> folderIds = orderTaskBeans.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList());

        String reason = wrapperBean.getParamValue("reason");
        orderTaskBeans.forEach(t -> {
            t.setStatus("abnormal");
            t.setReason(reason);
        });
        orderTaskService.getDao().fastUpdate(orderTaskBeans, "status", "reason");
        Long runId = orderTaskBeans.get(0).getRunId();
        List<LimsOrderTaskBean> taskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("runId", runId).filter(MatchPattern.EQ)
                .match("status", "logged").filter(MatchPattern.EQ));
        if (CollectionUtils.isEmpty(taskBeans)) {
            LimsRunBean runBean = new LimsRunBean();
            runBean.setStatus("abnormal");
            runBean.setId(runId);
            getDao().update(runBean, "status");
        }

        //任务维度插入操作记录
        List<Long> taskIds = orderTaskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_ENTER"), I18nHelper.getMessage("GIKAM.TAB.STOP_TASK"), reason);
        List<Long> sampleIds = orderTaskBeans.stream().map(LimsOrderTaskBean::getSampleId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.RESULT_ENTER"), I18nHelper.getMessage("GIKAM.TAB.STOP_TASK"), reason);

        limsBatchSampleProductService.setBatchProductStatus(folderIds);
    }

    @Transactional
    @Override
    public void abnormalPass(RestJsonWrapperBean wrapperBean) {
        List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        List<LimsOrderTaskBean> orderTaskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("parallelId", parallelIds).filter(MatchPattern.OR)
                .match("status", "abnormal").filter(MatchPattern.EQ));
        if (CollectionUtils.isEmpty(orderTaskBeans)) return;
        List<Long> folderIdList = orderTaskBeans.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList());

        passReview(orderTaskBeans, false);

        //任务维度插入操作记录
        List<Long> taskIds = orderTaskBeans.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("CORE.MENU.MENUNAME.NGS_TEST_ABNORMAL"), I18nHelper.getMessage("继续实验"), "");
        List<Long> sampleIds = orderTaskBeans.stream().map(LimsOrderTaskBean::getSampleId).distinct().collect(Collectors.toList());
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("CORE.MENU.MENUNAME.NGS_TEST_ABNORMAL"), I18nHelper.getMessage("继续实验"), "");

        limsBatchSampleProductService.setBatchProductStatus(folderIdList);
    }

    @Transactional
    @Override
    public void abnormalStop(RestJsonWrapperBean wrapperBean) {
        List<LimsOrderTaskBean> parse = wrapperBean.parse(LimsOrderTaskBean.class);
        if (CollectionUtils.isEmpty(parse)) return;
        String reason = wrapperBean.getParamValue("reason");
        List<Long> parallelIds = parse.stream().map(LimsOrderTaskBean::getParallelId).collect(Collectors.toList());
        List<LimsOrderTaskBean> stopTaskList = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("parallelId", parallelIds).filter(MatchPattern.OR));

        List<Long> folderIdList = stopTaskList.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList());
        List<Long> orderIdList = stopTaskList.stream().map(LimsOrderTaskBean::getOrderId).distinct().collect(Collectors.toList());
        List<Long> sampleIds = stopTaskList.stream().map(LimsOrderTaskBean::getSampleId).distinct().collect(Collectors.toList());

        this.abnormalStop(stopTaskList, reason);

        //任务维度插入操作记录
        List<Long> taskIds = stopTaskList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        auditRecordService.insertAuditRecords(taskIds, "T_LIMS_ORDER_TASK", I18nHelper.getMessage("CORE.MENU.MENUNAME.NGS_TEST_ABNORMAL"), I18nHelper.getMessage("终止实验"), reason);
        auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", I18nHelper.getMessage("CORE.MENU.MENUNAME.NGS_TEST_ABNORMAL"), I18nHelper.getMessage("终止实验"), reason);

//        limsBatchSampleProductService.setBatchProductStatus(folderIdList);
        limsBatchSampleProductService.setBatchProductWithStatus(folderIdList, "expStop");
    }

    @Transactional
    @Override
    public void abnormalStop(List<LimsOrderTaskBean> stopTaskList, String reason) {
        List<Long> folderIdList = stopTaskList.stream().map(LimsOrderTaskBean::getFolderId).distinct().collect(Collectors.toList());
        List<Long> orderIdList = stopTaskList.stream().map(LimsOrderTaskBean::getOrderId).distinct().collect(Collectors.toList());
        List<Long> sampleIds = stopTaskList.stream().map(LimsOrderTaskBean::getSampleId).distinct().collect(Collectors.toList());

        List<LimsOrderTaskBean> allOrderTaskBeans = orderTaskService.getDao().selectListByOneColumnValues(folderIdList, "folderId");
        List<LimsOrderTaskBean> newAllOrderTaskBeans = new ArrayList<>();
        for (LimsOrderTaskBean orderTaskBean : allOrderTaskBeans) {
            if (!StringUtils.equals("done", orderTaskBean.getStatus()) && !StringUtils.equals("stop", orderTaskBean.getStatus())) {
                newAllOrderTaskBeans.add(orderTaskBean);
            }
        }
        // 需要终止的任务单
        List<Long> newFolderIds = new ArrayList<>();
        for (Long folderId : folderIdList) {
            Long allCount = 0L;
            for (LimsOrderTaskBean orderTaskBean : newAllOrderTaskBeans) {
                if (StringUtils.equals(orderTaskBean.getFolderId().toString(), folderId.toString())) {
                    allCount = allCount + 1;
                }
            }
            Long preCount = 0L;
            for (LimsOrderTaskBean orderTaskBean : stopTaskList) {
                if (StringUtils.equals(orderTaskBean.getFolderId().toString(), folderId.toString())) {
                    preCount = preCount + 1;
                }
            }
            if (allCount.equals(preCount)) {
                newFolderIds.add(folderId);
            }
        }

        List<LimsFolderBean> updateFolderList = newFolderIds.stream().map(m -> {
            LimsFolderBean updateFolder = new LimsFolderBean();
            updateFolder.setId(m);
            updateFolder.setStatus("stop");
            return updateFolder;
        }).collect(Collectors.toList());
        folderService.getDao().fastUpdate(updateFolderList, "status");

        LimsOrderBean updateOrder = new LimsOrderBean();
        updateOrder.setStatus("stop");
        orderService.getDao().updateByIds(updateOrder, orderIdList, "status");

        LimsSampleBean updateSample = new LimsSampleBean();
        updateSample.setStatus("stop");
        sampleService.getDao().updateByIds(updateSample, sampleIds, "status");

        List<Long> orderTaskIds = stopTaskList.stream().map(LimsOrderTaskBean::getId).collect(Collectors.toList());
        List<LimsSampleDerivativeBean> derivativeBeans = derivativeService.selectListByFilter(SearchFilter.instance().match("orderTaskId", orderTaskIds).filter(MatchPattern.OR));
        if (!derivativeBeans.isEmpty()) {
            List<Long> deriSampleIds = derivativeBeans.stream().map(LimsSampleDerivativeBean::getDerivativeId).distinct().collect(Collectors.toList());
            LimsSampleBean update = new LimsSampleBean();
            update.setHandleType("wait");
            sampleService.getDao().updateByIds(update, deriSampleIds, "handleType");
        }

        List<LimsPreOrderTaskBean> stopPreOrderTaskList = new ArrayList<>();
        List<LimsPreOrderTaskBean> searchBeans = preOrderTaskService.selectListByFilter(SearchFilter.instance()
                .match("folderId", folderIdList).filter(MatchPattern.OR)
                .match("status", "done").filter(MatchPattern.DIFFER));
        stopTaskList.forEach(task -> {
            List<LimsPreOrderTaskBean> folderPreOrderTasks = searchBeans.stream().filter(e -> e.getFolderId().equals(task.getFolderId())).collect(Collectors.toList());
            if (!folderPreOrderTasks.isEmpty() && newFolderIds.stream().anyMatch(e -> e.equals(task.getFolderId()))) {
                // 获取当前终止的工序
                Optional<LimsPreOrderTaskBean> optional = folderPreOrderTasks.stream().filter(e -> e.getId().equals(task.getPreOrderTaskId())).findFirst();
                if (optional.isPresent()) {
                    stopPreOrderTaskList.add(optional.get());
                    // 根据上一道工序id获取对应流程的后续工序
                    getRelatedTestCodes(optional.get(), folderPreOrderTasks, stopPreOrderTaskList);
                }
            }
            task.setStatus("stop");
            task.setReason(reason);
        });
        orderTaskService.getDao().fastUpdate(stopTaskList, "status", "reason");
        if (!stopPreOrderTaskList.isEmpty()) {
            stopPreOrderTaskList.forEach(preTask -> {
                preTask.setStatus("stop");
            });
            preOrderTaskService.getDao().fastUpdate(stopPreOrderTaskList, "STATUS");
        }
        // 终止的任务，如果有同一批衍生物完成的，其他衍生物继续进行， preId 相同
        createNextOrderTask(stopTaskList);
    }

    private void getRelatedTestCodes(LimsPreOrderTaskBean currentPreOrderTask, List<LimsPreOrderTaskBean> folderPreOrderTasks, List<LimsPreOrderTaskBean> stopPreOrderTaskList) {
        for (LimsPreOrderTaskBean nextPreOrderTaskBean : folderPreOrderTasks) {
            if (!StringUtils.isBlank(nextPreOrderTaskBean.getLastEtTestIds()) && checkExists(nextPreOrderTaskBean.getLastEtTestIds(), String.valueOf(currentPreOrderTask.getEtTestId()))) {
                if (!stopPreOrderTaskList.contains(nextPreOrderTaskBean)) {
                    stopPreOrderTaskList.add(nextPreOrderTaskBean);
                    getRelatedTestCodes(nextPreOrderTaskBean, folderPreOrderTasks, stopPreOrderTaskList);
                }
            }
        }
    }

    @Override
    @Transactional
    public JSONObject resultEditHandOver(RestJsonWrapperBean wrapperBean) {
        JSONObject req = new JSONObject();

        List<LimsRunBean> runs = wrapperBean.parse(LimsRunBean.class);
        String testerId = wrapperBean.getParamValue("testerId");
        String tester = wrapperBean.getParamValue("tester");
        if (CollectionUtils.isEmpty(runs)) {
            return req;
        }
        runs.forEach(r -> {
            r.setAnalystId(testerId);
            r.setAnalystName(tester);
        });
        getDao().fastUpdate(runs, "analystId", "analystName");
        List<Long> runIds = runs.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));
        taskBeans.forEach(r -> {
            r.setTesterId(testerId);
            r.setTester(tester);
        });
        orderTaskService.getDao().fastUpdate(taskBeans, "testerId", "tester");

        return req;
    }

    @Override
    @Transactional
    public JSONObject resultAuditHandOver(RestJsonWrapperBean wrapperBean) {
        JSONObject req = new JSONObject();

        List<LimsRunBean> runs = wrapperBean.parse(LimsRunBean.class);
        String reviewer = wrapperBean.getParamValue("reviewer");
        String reviewerId = wrapperBean.getParamValue("reviewerId");
        if (CollectionUtils.isEmpty(runs)) {
            return req;
        }
        runs.forEach(r -> {
            r.setReviewer(reviewer);
            r.setReviewerId(reviewerId);
        });
        getDao().fastUpdate(runs, "reviewer", "reviewerId");
        List<Long> runIds = runs.stream().map(LimsRunBean::getId).collect(Collectors.toList());
        List<LimsOrderTaskBean> taskBeans = orderTaskService.selectListByFilter(SearchFilter.instance()
                .match("runId", runIds).filter(MatchPattern.OR));
        taskBeans.forEach(r -> {
            r.setReviewer(reviewer);
            r.setReviewerId(reviewerId);
        });
        orderTaskService.getDao().fastUpdate(taskBeans, "reviewer", "reviewerId");

        return req;
    }

/*    @Transactional
    public void setBatchProductStatus(List<Long> folderIds) {
        List<LimsFolderBean> folderBeans = folderService.selectListByIds(folderIds);
        if (folderBeans.isEmpty()) {
            return;
        }
        List<LimsBatchSampleProductBean> batchProductSelectBy = new ArrayList<>();

        folderBeans.forEach(f -> {
            LimsBatchSampleProductBean bean = new LimsBatchSampleProductBean();
            bean.setProductCode(f.getProductCode());// 质控样得项目没有productid，只能通过code
            bean.setBatchSampleId(f.getBatchSampleId());
            batchProductSelectBy.add(bean);
        });
        if (!batchProductSelectBy.isEmpty()) {
            List<LimsBatchSampleProductBean> batchProductUpdateBy = limsBatchSampleProductService.getDao().selectList(batchProductSelectBy, Arrays.asList("batchSampleId", "productCode"), Arrays.asList("id", "batchSampleId", "productCode"));
//            List<LimsOrderTaskBean> odTasks = orderTaskService.selectListByFilter(SearchFilter.instance().match("folderId", folderIds).filter(MatchPattern.OR));
            List<LimsOrderTaskBean> odTasks = orderTaskService.getDao().selectListByOneColumnValues(folderIds, "folderId", Arrays.asList("Id", "folderId", "status"));

            batchProductUpdateBy.forEach(bp -> {
                List<Long> tempFolderIds = folderBeans.stream().filter(f -> f.getProductCode().equals(bp.getProductCode()) && f.getBatchSampleId().equals(bp.getBatchSampleId())).map(LimsFolderBean::getId).collect(Collectors.toList());
                AtomicInteger doneNum = new AtomicInteger(0);
                AtomicInteger abnormalNum = new AtomicInteger(0);
                AtomicInteger stopNum = new AtomicInteger(0);
                AtomicInteger doingNum = new AtomicInteger(0);
                odTasks.stream().filter(ot -> tempFolderIds.contains(ot.getFolderId())).forEach(ot -> {
                    switch (ot.getStatus()) {
                        case "done": {
                            doneNum.getAndIncrement();
                        }
                        break;
                        case "draft":
                        case "logged":
                        case "approve": {
                            doingNum.getAndIncrement();
                        }
                        break;
                        case "abnormal": {
                            abnormalNum.getAndIncrement();
                        }
                        break;
                        case "stop": {
                            stopNum.getAndIncrement();
                        }
                        break;
                    }
                });
                bp.setStatus("inExperiment");
                // 如果终止和异常数都为0
                if (stopNum.get() == 0 && abnormalNum.get() == 0) {
                    if (doingNum.get() == 0) {
                        // 正在进行的任务不为0
                        bp.setStatus("expDone");
                        return;
                    } else {
                        // 全都结束
                        bp.setStatus("inExperiment");
                        return;
                    }
                }
                if (abnormalNum.get() > 0) {
                    bp.setStatus("expAbnormal");
                    return;
                }
                // 终止任务不为0，且没有正在进行的任务、异常的任务
                if (stopNum.get() > 0 && doingNum.get() == 0 && abnormalNum.get() == 0) {
                    bp.setStatus("expStop");
                    return;
                }
            });
            if (!batchProductUpdateBy.isEmpty()) {
                limsBatchSampleProductService.getDao().fastUpdate(batchProductUpdateBy, "status");
            }
        }
    }*/
}
